#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <event.h>
#include <errno.h>

#include <dlfcn.h>

#include "server.h"
#include "log.h"

void read_handler(int fd, short event, void *arg)
{
    char buf[1024];
    char tbuf[1024];
    int i;
    int ret;
    struct sockaddr_in* s_in;
    struct event* ev;

    void *handle;
    
    int (*process)(const char*, int, char*);
    char* error;
    
    memset(buf, 0x0, sizeof(buf));
    memset(tbuf, 0x0, sizeof(tbuf));
    
    ev = (struct event*)arg;
    
    debug("reading...\n");
    ret = read(fd, buf, 1024); 
    debug("RET=%d\n", ret);
    debug("READ=%s\n", buf);
/*
    debug("[%s:%d]\n", 
          inet_ntoa(s_in->sin_addr), ntohs(s_in->sin_port));
*/  
    /* logic process */
    if ( ret > 0) {

        handle = dlopen("libmylogic.so", RTLD_LAZY);

        if(!handle) {
            debug("load dynimic error\n");
            
        } else {
            dlerror();
            *(void **)(&process) = dlsym(handle, "process");
            
            if ((error = dlerror()) != NULL)  {
                debug("Find process error\n");
            } else {
                ret = (*process)(buf, ret, tbuf);
                
                if (ret >0) {
                    write(fd, tbuf, ret);
                }
            }

            
        }
        
    } else {
        event_del(ev);
        close(fd);
    }

/*    close(fd);         */
}

void accept_handler(int fd, short event, void *arg)
{
    struct sockaddr_in s_in;
    socklen_t len = sizeof(s_in);

    int ns = accept(fd, (struct sockaddr*)&s_in, &len);

    struct event *ev = (struct event*)malloc(sizeof(struct event));
    event_set(ev, ns, EV_READ|EV_PERSIST, read_handler, ev);
    
    event_add(ev, NULL);

    print_log(LOG_INFO, "new connection from [%s:%d]...\n", 
              inet_ntoa(s_in.sin_addr), ntohs(s_in.sin_port));
}


int main(int argc, char* argv[])
{
    struct sockaddr_in svr;
    int socket_fd;
    struct event listen_evt;

    if (init_log() != 0) {
        fprintf(stderr, "message log failed\n");
    }
    
    print_log(LOG_INFO, "Server start ...");
    
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);

    bzero(&svr, sizeof(svr));
    
    svr.sin_family = AF_INET;
    svr.sin_port = htons(GUEST_PORT);
    svr.sin_addr.s_addr = INADDR_ANY;
    
    bind(socket_fd, (struct sockaddr*)&svr, sizeof(svr));
    
    if (listen(socket_fd, 10) != 0) {
        print_log(LOG_ERROR, " listen on [%d] failed", GUEST_PORT);
    }

    print_log(LOG_INFO, " listen on [%d] ", GUEST_PORT);
    
    event_init();
    
    event_set(&listen_evt, socket_fd, EV_READ|EV_PERSIST, 
	      accept_handler, & listen_evt);

    event_add(&listen_evt, NULL);
    event_dispatch();
    
    return 0;
}
